package com.nanxhs.concurrent.thread.message;

import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 *  为了测试 Object.wait 与 Object.notify的使用
 * @author: haibin.tang
 * @date: 2021/1/27
 */
public class ChatService {
    /**
     * 监视器锁
     */
    private final Object MONITOR = new Object();
    /**
     * 问题
     */
    private Question question;

    /**
     * 问题线程
     */
    public void a() {
        new Thread(() -> {
            synchronized (MONITOR) {
                while (true) {
                    try {
                        question = new Question((int)(Math.random() * 1000), (int)(Math.random() * 100));
                        System.out.println("问题: " + question.getA() + " + " + question.getB() + " = ?");
                        //随机唤醒其它等待在 MONITOR 监视器的线程
                        MONITOR.notify();
                        //让当前线程等待并且释放锁
                        MONITOR.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    /**
     * 计算答案的线程
     */
    public void b() {
         new Thread(() -> {
            synchronized (MONITOR) {
                while (true) {
                    if (Objects.isNull(question)) {
                        try {
                            //随机唤醒其它等待在 MONITOR 监视器的线程
                            MONITOR.notify();
                            //让当前线程等待并且释放锁
                            MONITOR.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        //当前线程阻塞1秒
                        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
                        System.out.println("答案: " + (question.getA() + question.getB()));
                        //当前线程阻塞1秒
                        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
                        question = null;
                        //随机唤醒其它等待在 MONITOR 监视器的线程
                        MONITOR.notify();
                        try {
                            //让当前线程等待并且释放锁
                            MONITOR.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }

    public static void main(String[] args) {
        ChatService chatService = new ChatService();
        chatService.a();
        chatService.b();
    }
}
